package com.wenbing.miio.mi.device.simulator;

import com.wenbing.miio.core.*;
import com.wenbing.miio.core.exception.NetworkLayerException;
import com.wenbing.miio.mi.MessageFrame;
import com.wenbing.miio.mi.MiFrameLayer;
import com.wenbing.miio.mi.MiDeviceUtil;
import com.wenbing.miio.util.EmptyObjects;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * @author wen bing
 * @projectName: miio
 * @package: com.wenbing.miio.mi.device.simulator
 * @className: Layer
 * @date 2024/09/20 16:17
 **/

public class ServerModeAdapterLayer extends AbstractShareContextNetworkLayer {

    @Override
    protected ByteBuffer unpacking(NetworkLayerContext context, ByteBuffer packingData) throws IOException, NetworkLayerException {
        return packingData;
    }

    @Override
    protected ByteBuffer packing(NetworkLayerContext context, ByteBuffer packingData) throws IOException, NetworkLayerException {
        context.setAttribute(MiFrameLayer.ATTR_DID, MiDeviceUtil.getDeviceId(this));
        context.setAttribute(MiFrameLayer.ATTR_FLAGS, 0);
        context.setAttribute(MiFrameLayer.ATTR_TIMESTAMP,  MiDeviceUtil.getRunningTime(this));
        return packingData;
    }


    private boolean deliverLowerLayer(NetworkLayerContext context) throws NetworkLayerException, IOException {
        int flags = context.getAttribute(MiFrameLayer.ATTR_FLAGS);
        // 处理hello包
        if (flags == MessageFrame.FLAGS_HELLO) {
            LOGGER.info("hello package be found, outbound immediately");
            outbound(context, EmptyObjects.byteBuffer);
            return false;
        }
        return true;
    }

    private boolean dropFrame(Context context) {
        int flags = context.getAttribute(MiFrameLayer.ATTR_FLAGS);
        if (flags == MessageFrame.FLAGS_HELLO) {
            return false;
        }
        long timestamp = context.getAttribute(MiFrameLayer.ATTR_TIMESTAMP);
        long runningTime = MiDeviceUtil.getRunningTime(this);
        // 无效时间戳 丢弃
        return timestamp > runningTime || runningTime - timestamp > 3;
    }

    @Override
    protected void deliverLowerLayer(NetworkLayerContext context, ByteBuffer packingData) throws NetworkLayerException, IOException {
        // 是否丢弃该数据帧
        if (dropFrame(context)) {
            return;
        }
        // 是否交付下层
        if (deliverLowerLayer(context)) {
            super.deliverLowerLayer(context, packingData);
        }
    }
}
